<template>
  <div class="image-upload-container">
    <!-- 单张图片上传模式 -->
    <div v-if="!multiple" class="single-image-upload">
      <el-upload
        v-if="!hasImage"
        class="image-uploader single-uploader"
        :action="fullUploadUrl"
        :headers="computedHeaders"
        :data="extraData"
        :multiple="false"
        list-type="picture-card"
        :limit="1"
        :on-success="handleSuccess"
        :on-error="handleError"
        :on-preview="handlePreview"
        :before-upload="beforeUpload"
        v-model:file-list="fileList"
      >
        <el-icon><Plus /></el-icon>
      </el-upload>

      <div v-else class="image-preview">
        <img :src="currentImageUrl" alt="图片预览" class="preview-image" />
        <div class="image-actions">
          <el-button
            type="danger"
            size="small"
            circle
            @click="removeImage"
            class="remove-btn"
          >
            <el-icon><Delete /></el-icon>
          </el-button>
          <el-button
            type="primary"
            size="small"
            circle
            @click="triggerPreview"
            class="preview-btn"
          >
            <el-icon><ZoomIn /></el-icon>
          </el-button>
        </div>
      </div>
    </div>

    <!-- 多张图片上传模式 -->
    <el-upload
      v-else
      class="image-uploader"
      :action="fullUploadUrl"
      :headers="computedHeaders"
      :data="extraData"
      :multiple="multiple"
      list-type="picture-card"
      :limit="limit"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :before-upload="beforeUpload"
      v-model:file-list="fileList"
    >
      <el-icon><Plus /></el-icon>
    </el-upload>

    <el-dialog v-model="dialogVisible" title="图片预览" width="50%">
      <img :src="previewImageUrl" alt="预览" style="width: 100%" />
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Delete, ZoomIn } from '@element-plus/icons-vue'

// Props
const props = defineProps({
  headers: Object,
  extraData: Object,
  multiple: Boolean,
  limit: { type: Number, default: 5 },
  modelValue: { type: [Array, String], default: () => [] },
})

// Emits
const emit = defineEmits(['update:modelValue', 'success'])

// 文件列表绑定
const fileList = ref([])

// 预览控制
const dialogVisible = ref(false)
const previewImageUrl = ref('')

// 上传地址
const fullUploadUrl = computed(() => {
  const base = import.meta.env.VITE_API_BASE_URL || ''
  return `${base}/common/upload`
})

// 带 token 的 headers
const computedHeaders = computed(() => ({
  ...props.headers,
  Authorization: `Bearer ${localStorage.getItem('token') || ''}`
}))

// 同步父组件传入的 modelValue（初始化或变更时）
watch(() => props.modelValue, (val) => {
  const urls = Array.isArray(val) ? val : (val ? [val] : [])
  fileList.value = urls.map(url => ({
    name: url.split('/').pop(),
    url,
    status: 'done'
  }))
}, { immediate: true })

// 上传前校验
const beforeUpload = (file) => {
  const isImage = file.type.startsWith('image/')
  if (!isImage) {
    ElMessage.error('只能上传图片文件！')
    return false
  }
  return true
}

// 上传成功
const handleSuccess = (response, file) => {
  ElMessage.success('上传成功')
  emit('success', response)

  const target = fileList.value.find(f => f.uid === file.uid)
  if (target) {
    target.response = response
    target.url = response.data?.url || target.url
  }

  updateModelValue()
}

// 上传失败
const handleError = (err) => {
  ElMessage.error('上传失败')
  console.error(err)
}

// 预览
const handlePreview = (file) => {
  previewImageUrl.value = file.url || file.response?.data?.url || ''
  dialogVisible.value = true
}

// 删除文件
const handleRemove = (file) => {
  fileList.value = fileList.value.filter(f => f.uid !== file.uid)
  updateModelValue()
}

// 计算属性：单图模式下是否有图片
const hasImage = computed(() => {
  return fileList.value.length > 0 && fileList.value[0].url
})

// 计算属性：当前图片URL
const currentImageUrl = computed(() => {
  if (!hasImage.value) return ''
  return fileList.value[0].response?.data?.url || fileList.value[0].url
})

// 移除单张图片
const removeImage = () => {
  fileList.value = []
  updateModelValue()
}

// 触发预览
const triggerPreview = () => {
  if (hasImage.value) {
    previewImageUrl.value = currentImageUrl.value
    dialogVisible.value = true
  }
}

// 更新父组件的 v-model
const updateModelValue = () => {
  const urls = fileList.value.map(f => f.response?.data?.url || f.url)
  if (props.multiple) {
    emit('update:modelValue', urls)
  } else {
    emit('update:modelValue', urls[0] || '')
  }
}
</script>

<style scoped>
.image-upload-container {
  display: inline-block;
}

.single-image-upload {
  display: inline-block;
}

.single-uploader :deep(.el-upload--picture-card) {
  width: 148px;
  height: 148px;
  line-height: 148px;
}

.image-preview {
  position: relative;
  display: inline-block;
  width: 148px;
  height: 148px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px dashed #d9d9d9;
}

.preview-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-actions {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  gap: 8px;
  opacity: 0;
  transition: opacity 0.3s;
}

.image-preview:hover .image-actions {
  opacity: 1;
}

.remove-btn,
.preview-btn {
  background-color: rgba(0, 0, 0, 0.6);
  border: none;
  color: white;
}

.remove-btn:hover,
.preview-btn:hover {
  background-color: rgba(0, 0, 0, 0.8);
}

:deep(.el-upload--picture-card) {
  transition: all 0.3s;
}

:deep(.el-upload--picture-card:hover) {
  border-color: #409eff;
}
</style>
